/* 
 * LogAspect.java      1.00    2008-01-11
 *
 * Copyright (c) 2010 monolist. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information
 * of monolist.  You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement
 * you entered into with monolist.
 */
package doit.framework.aspect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.util.StopWatch;

import doit.framework.util.Config;

/**
 * <pre>
 * system      : 공통
 * menu        : 공통
 * source      : LogAspect.java
 * description : Log Annotation
 * </pre> 
 * @version
 * <pre> 
 * 1.0  2008-01-11  monolist  최초 작성
 * 1.1  
 * </pre>
 */

@SuppressWarnings("unchecked")
@Aspect
public class LogAspect {
	private static Log logger = LogFactory.getLog(LogAspect.class);
	
	private final int resultSetEmpty = 20;
	private final String mapType 		= 	".HashMap";
	private final String arrayListtype 	= 	".ArrayList";
	private final String listType 		= 	".List";
	private final String domainType 	= 	".domain";
	
	public static final String DEFAULT_CHARSET = "MS949";
	public static final String KOR_CHARSET = "MS949"; //EUC-KR
	public static final String ENG_CHARSET = "ISO-8859-1";
	
	@Before("execution(* *..ControllerExecuteChecker.annotation(..))")
	public void before(JoinPoint joinPoint) {
		if (!Boolean.valueOf(Config.getString("doit.common.log.enable-info"))) {
			return;
		}
		Object[] obj = joinPoint.getArgs();
		HttpServletRequest request = (HttpServletRequest)obj[0];
		String className = joinPoint.getSignature().getDeclaringType().getName();
		String emptyCalssName = "";
		Enumeration e = request.getParameterNames();		
		boolean isElement = false;
		for (int i = 0 ; i < 79 - className.length() ; i++) {
			emptyCalssName += " ";
		}
		logger.debug("\n-------------------------------------------------------------------------------------------------------");
    	logger.debug("| PROCESS CONTROLLER = " + className + emptyCalssName + "|");
    	logger.debug("-------------------------------------------------------------------------------------------------------");
		if (e.hasMoreElements()) {
			isElement = true;
			logger.debug("**************************************** REQUEST PARAMETER LOG START **********************************");
			logger.debug("-------------------------------------------------------------------------------------------------------");
			logger.debug("|                  key                  	  |                      value                        |");
			logger.debug("-------------------------------------------------------------------------------------------------------");
		}
		while (e.hasMoreElements()) {
			String key = (String) e.nextElement();
			String value = request.getParameter(key);
			String emptyKey = "";
			String emptyKeyValue = "";
			for (int i = 0 ; i < 47 - key.length() ; i++) {
				emptyKey += " ";
			}
			for (int i = 0 ; i < 50 - value.length() ; i++) {
				emptyKeyValue += " ";
			}
			logger.debug("| " + key + emptyKey + " | " + value + emptyKeyValue + "|");
			logger.debug("-------------------------------------------------------------------------------------------------------");
		}
		if (isElement) {
			logger.debug("****************************************  REQUEST PARAMETER LOG END ***********************************\n");
		}
	}
	
	@Before("execution(* *..DWRExecuteChecker.annotation(..))")
	public void beforeDWR(JoinPoint joinPoint) {
		if (!Boolean.valueOf(Config.getString("doit.common.log.enable-info"))) {
			return;
		}
		Object[] obj = joinPoint.getArgs();
		Map[] input = null;
		try {
			if (obj[0] instanceof Map) {
				input = new Map[1];
				input[0] = (Map) obj[0];
			}
			else if( obj[0] instanceof Map[])
			{
				input = (Map[])obj[0];
			}
		} catch (Exception e) {
			return;
		}
		String className = joinPoint.getSignature().getDeclaringType().getName();
		String emptyCalssName = "";
		
		boolean isElement = false;
		for (int j = 0 ; j < 86 - className.length() ; j++) {
			emptyCalssName += " ";
		}
		logger.debug("\n-------------------------------------------------------------------------------------------------------");
		logger.debug("| PROCESS DWR = " + className + emptyCalssName + "|");
		logger.debug("-------------------------------------------------------------------------------------------------------");

		for( int i = 0; i<input.length; i++)
		{
			Set keyset = input[i].keySet();
			Iterator iterator = keyset.iterator();
			if (iterator.hasNext()) {
				isElement = true;
				logger.debug("**************************************** REQUEST PARAMETER LOG START **********************************");
				logger.debug("-------------------------------------------------------------------------------------------------------");
				logger.debug("|                  key                  	  |                      value                        |");
				logger.debug("-------------------------------------------------------------------------------------------------------");
			}
			while (iterator.hasNext()) {
				String key = (String) iterator.next();
				String value = (String)input[i].get(key);
				if( value == null)
					value = "";
				String emptyKey = "";
				String emptyKeyValue = "";
				for (int x = 0 ; x < 47 - key.length() ; x++) {
					emptyKey += " ";
				}
				if (value.length() > 50) {
					value = value.substring(0, 48) + "..";
				} else {
					for (int x = 0 ; x < 50 - value.length() ; x++) {
						emptyKeyValue += " ";
					}
				}
				logger.debug("| " + key + emptyKey + " | " + value + emptyKeyValue + "|");
				logger.debug("-------------------------------------------------------------------------------------------------------");
			}
			if (isElement) {
				logger.debug("****************************************  REQUEST PARAMETER LOG END ***********************************\n");
			}
		}
	}
	
	@Around("execution(* *..*DAO.*(..))")
	public Object aroundDAO(ProceedingJoinPoint joinPoint) throws Throwable {
		StopWatch sw = new StopWatch(joinPoint.toShortString());
		sw.start();
		Object obj = null;
		try {
			obj = joinPoint.proceed();
        } 
		catch(Exception e) {
			e.printStackTrace();
		}
		finally {
        	sw.stop();
        	if (obj != null) {
	        	if (Boolean.valueOf(Config.getString("doit.common.log.enable-debug"))) {
					logger.debug("*****************************************  RESULT VALUE LOG START *************************************\n");
					dataSetLog(obj);
					logger.debug("");
					logger.debug("******************************************  RESULT VALUE LOG END **************************************\n");
				}
        	}
        	if (!Boolean.valueOf(Config.getString("doit.common.log.enable-debug"))) {
    			return obj;
    		}
        	String emptyTotalTime = "";
        	String totalTime = String.valueOf(sw.getTotalTimeSeconds());
        	for (int i = 0 ; i < 80 - totalTime.length() ; i++) {
        		emptyTotalTime += " ";
			}
        	logger.debug("********************************************** DAO PROCESS TIME ***************************************");
        	logger.debug("-------------------------------------------------------------------------------------------------------");
        	logger.debug("| TOTAL TIME = " + sw.getTotalTimeSeconds() + " SECOND" + emptyTotalTime + "|");
        	logger.debug("-------------------------------------------------------------------------------------------------------\n\n\n");
        }
		return obj;
	}
	
	public void dataSetLog(Object obj) throws Throwable {
		try {
			Class clazz_ = obj.getClass();
			String objType = clazz_.getName();
			if (objType.indexOf(this.mapType) > -1) {
				Map map = (Map)obj;
				Set set = map.keySet();
				Iterator iterator = set.iterator();
				while(iterator.hasNext()) {
					String key = String.valueOf(iterator.next());
					Object objData = map.get(key);
					this.dataSetLog(objData);
				}
			} 
			else if (objType.indexOf(this.listType) > -1 || objType.indexOf(this.arrayListtype) > -1) {
				ArrayList list = (ArrayList)obj;
				if (list.size() > 0) {
					Object tempObj = list.get(0);
					Class tempClazz = tempObj.getClass();
					if (tempClazz.getName().indexOf(this.domainType) > -1) {
						if (tempClazz.getName().indexOf(this.domainType) > -1) {
							for (int i = 0 ; i < list.size() ; i++) {
								Object o = list.get(i);
								if(i == 0) {
									this.loggingDomainHeader(o);
								}
								this.loggingDomain(o);
							}	
						}
					} 
					else {
						for (int i = 0 ; i < list.size() ; i++ ) {
							this.dataSetLog(list.get(i));
						}
					}

				}
			} else if (objType.indexOf(this.domainType) > -1) {
				this.loggingDomainHeader(obj);
				this.loggingDomain(obj);
			} else {
				String temp = "";
				for(int i=0; i<48-obj.toString().length();i++) {
					temp += " ";
				}
				logger.debug("------------------------------------------------------------------------------------------------------");
				logger.debug("|                결과값                                                        |  " + String.valueOf( obj) + temp + "|");
				logger.debug("------------------------------------------------------------------------------------------------------");
			}
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	
	private void loggingDomainHeader(Object obj) {
		try {
			Class clazz = obj.getClass();
			Field[] field = clazz.getDeclaredFields();
			String[] header = new String[field.length];
			for(int i=0;i<field.length;i++) {
				String empty = ""; 
				String getMethod = field[i].getName().substring(0, 1).toUpperCase() +  field[i].getName().substring(1);
				if (getMethod.length() > resultSetEmpty) {
					getMethod = getMethod.substring(0,18) + "..";
				}
				for (int k = 0 ; k < resultSetEmpty - getMethod.length() ; k++) {
					empty += " ";
				}
				header[i]  = getMethod + empty + "|";
			}
			String headerTemp = "| ";
			for(int i = 0; i<header.length; i++) {
				headerTemp +=  header[i];
			}
			String temp1 = "";
			for (int i = 0 ; i < headerTemp.length() ; i++) {
				temp1 += "-";
			}
			logger.debug(temp1);
			logger.debug(headerTemp);
			logger.debug(temp1);
			
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}

	private void loggingDomain(Object obj) {
		try {
			Class clazz = obj.getClass();
			Field[] field = clazz.getDeclaredFields();
			String[] header = new String[field.length];
			String[][] logging = new String[1][field.length];
			for(int i=0 ; i<field.length ; i++) {
				String getMethod = field[i].getName().substring(0, 1).toUpperCase() +  field[i].getName().substring(1);
				Method method = clazz.getMethod("get" + getMethod);
				String temp = String.valueOf(method.invoke(obj));
				String empty = new String(); 
				if (getMethod.length() > resultSetEmpty) {
					getMethod = getMethod.substring(0,18) + "..";
				}
				byte[] headerTemp = getMethod.getBytes();
				for (int k = 0 ; k < resultSetEmpty - headerTemp.length ; k++) {
					empty += " ";
				}
				header[i]  = getMethod + empty + "|";
				empty = "";
				if (temp.length() > resultSetEmpty) {
					temp = temp.substring(0,18) + "..";
				}
				byte[] bTemp = temp.getBytes();
				for (int k = 0 ; k < resultSetEmpty - bTemp.length  ; k++) {
					empty += " ";
				}
				logging[0][i] = temp + empty + "|";
			}
			String headerTemp = "| ";
			for(int i = 0; i<header.length; i++) {
				headerTemp +=  header[i];
			}
			String temp1 = "";
			for (int i = 0 ; i < headerTemp.length() ; i++) {
				temp1 += "-";
			}
			for (int i = 0 ; i < logging.length ; i++) {
				String temp = "";
				for (int j = 0 ; j < logging[i].length ; j++) {
					temp += logging[i][j];
				}
				logger.debug("| " + temp);
			}
		} catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}
